package game.square;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import game.border.Border;
import game.border.Wall;
import game.border.WallWithDoor;

import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

/**
 * A testclass for the class Square.
 * 
 * @version	1.0
 * @author	Dries Liebens 
 * 			Loic Vercruysse
 */

public class SquareTest {

	private static Square square;
	private Border northDoorBorder;
	private Border southOpenDoorBorder;
	private Border floorDoorBorder;
	private Border ceilingDoorBorder;
//	private Border floorDoorBorder2; 
	private Square squareNorthBorder;
	
	@Before
	public void setUp() throws Exception {
		 square = new Square();
		 northDoorBorder = new Border(Direction.NORTH, new WallWithDoor());
		 southOpenDoorBorder = new Border(Direction.SOUTH, new WallWithDoor(true));
		 floorDoorBorder = new Border(Direction.FLOOR, new WallWithDoor(false));
		 ceilingDoorBorder = new Border(Direction.CEILING, new WallWithDoor(false));
//		 floorDoorBorder2 = new Border(Direction.FLOOR, new WallWithDoor(false));
		 squareNorthBorder = new Square(northDoorBorder);
	}

	

	@Test
	public final void defaultConstructor() {
		Square newSquare = new Square();
		assertEquals(0,Double.compare(20,newSquare.getTemperature(Temperature.CELCIUS)));
		assertEquals(0,Double.compare(0,newSquare.getHumidity()));
	}
	
	@Test
	public final void extendedConstructor_noError() {
		Square newSquare = new Square(50, Temperature.CELCIUS, 20,new Border(Direction.NORTH,new Wall()));
		assertEquals(0, Double.compare(50,newSquare.getTemperature(Temperature.CELCIUS)));
		assertEquals(0, Double.compare(20,newSquare.getHumidity()));
	}
		
	@Test (expected=IllegalArgumentException.class)
	public final void extendedConstructor_toLowTemperature_exception() {
		new Square(-201, Temperature.CELCIUS,101);
	}
	
	@Test (expected=IllegalArgumentException.class)
	public final void extendedConstructor_toHighTemperature_exception() {
		new Square(5001, Temperature.CELCIUS,101);
	}
	
	@Test
	public final void extendedConstructor_maximumTemperatureBorder() {
		new Square(5000, Temperature.CELCIUS,101);
	}
	
	@Test
	public final void extendedConstructor_minimumTemperatureBorder() {
		new Square(-200, Temperature.CELCIUS,101);
	}
	
	@Test
	public final void isValidTemperatureScale() {
		assertTrue(square.isValidTemperatureScale(Temperature.CELCIUS));
		assertTrue(square.isValidTemperatureScale(Temperature.FAHRENHEIT));
		assertTrue(square.isValidTemperatureScale(Temperature.KELVIN));
	}
	
	@Test
	public final void setTemperature_legalCase() {
		square.setTemperature(5000, Temperature.CELCIUS);
		assertEquals(0, Double.compare(5000, square.getTemperature(Temperature.CELCIUS)));
		square.setTemperature(-200, Temperature.CELCIUS);
		assertEquals(0, Double.compare(-200, square.getTemperature(Temperature.CELCIUS)));
		
		square.setTemperature(5273.15, Temperature.KELVIN);
		assertEquals(0, Double.compare(5000,square.getTemperature(Temperature.CELCIUS)));
		square.setTemperature(74, Temperature.KELVIN);
		assertEquals(0, Double.compare(74, square.getTemperature(Temperature.KELVIN)));
	}
	
	@Test (expected=IllegalArgumentException.class)
	public final void setTemperature_toLow_illegalCase() {
		square.setTemperature(-201, Temperature.CELCIUS);
	}
	
	@Test (expected=IllegalArgumentException.class)
	public final void setTemperature_toHigh_illegalCase() {
		square.setTemperature(5001, Temperature.CELCIUS);
	}
	
	@Test
	public final void canHaveAsTemperature() {
		assertTrue(square.canHaveAsTemperature(-200,Temperature.CELCIUS));
		assertTrue(square.canHaveAsTemperature(5000,Temperature.CELCIUS));
		assertTrue(square.canHaveAsTemperature(251,Temperature.CELCIUS));
		assertFalse(square.canHaveAsTemperature(-201,Temperature.CELCIUS));
		assertFalse(square.canHaveAsTemperature(5001,Temperature.CELCIUS));
	}
	
	@Test
	public final void setMaximumTemperature_legalCase() {
		square.setMaximumTemperature(20, Temperature.CELCIUS);
		square.setMaximumTemperature(50, Temperature.CELCIUS);
	}
	
	@Test (expected=IllegalArgumentException.class)
	public final void setMaximumTemperature_illegalCase() {
		square.setMaximumTemperature(19, Temperature.CELCIUS);
	}
	
	@Test
	public final void setMinimumTemperature_legalCase() {
		square.setMinimumTemperature(19, Temperature.CELCIUS);
		square.setMinimumTemperature(20, Temperature.CELCIUS);
	}
	
	@Test (expected=IllegalArgumentException.class)
	public final void setMinimumTemperature_illegalCase() {
		square.setMinimumTemperature(21, Temperature.CELCIUS);
	}
	
	@Test
	public final void canHaveAsMaximumTemperature() {
		square.setTemperature(-200, Temperature.CELCIUS);
		assertTrue(square.canHaveAsMaximumTemperature(10,Temperature.CELCIUS));
		assertTrue(square.canHaveAsMaximumTemperature(-200,Temperature.CELCIUS));
		assertFalse(square.canHaveAsMaximumTemperature(-201,Temperature.CELCIUS));
	}
	
	@Test
	public final void canHaveAsMinimumTemperature() {
		square.setTemperature(5000, Temperature.CELCIUS);
		assertTrue(square.canHaveAsMinimumTemperature(20, Temperature.CELCIUS));
		assertTrue(square.canHaveAsMinimumTemperature(5000, Temperature.CELCIUS));
		assertFalse(square.canHaveAsMinimumTemperature(5001, Temperature.CELCIUS));
	}
	
	@Test
	public final void setHumidity() {
		square.setHumidity(0);
		assertEquals(0,Double.compare(0, square.getHumidity()));
		square.setHumidity(50);
		assertEquals(0,Double.compare(50, square.getHumidity()));
		square.setHumidity(100);
		assertEquals(0,Double.compare(100, square.getHumidity()));
	}
	
	@Test
	public final void isValidHumidity() {
		assertTrue(square.isValidHumidity(0));
		assertTrue(square.isValidHumidity(100));
		assertTrue(square.isValidHumidity(50));
		assertFalse(square.isValidHumidity(101));
		assertFalse(square.isValidHumidity(-1));
	}
	
	@Test
	public final void rustDamage(){
		square.setHumidity(30);	
		assertEquals(0, square.calculateRustDamage());
		square.setHumidity(31);
		assertEquals(0, Double.compare(1/7, 1/7));
	}
	
	@Test
	public final void setThresholdHeatDamageTemperature_legalCase(){
		square.setThresholdHeatDamageTemperature(50, Temperature.CELCIUS);
		assertEquals(0,Double.compare(50,square.getThresholdHeatDamageTemperature(Temperature.CELCIUS)));
	}
	
	@Test (expected=IllegalArgumentException.class)
	public final void setThresholdHeatDamageTemperature_illegalCase() {
		square.setThresholdHeatDamageTemperature(-10, Temperature.CELCIUS);
	}
	
	@Test
	public final void isValidThresholdHeatDamageTemperature() {
		assertTrue(square.isValidThresholdHeatDamageTemperature(
				square.getThresholdColdDamageTemperature(Temperature.CELCIUS)+1,Temperature.CELCIUS));
		assertFalse(square.isValidThresholdHeatDamageTemperature(
				square.getThresholdColdDamageTemperature(Temperature.CELCIUS)-1,Temperature.CELCIUS));
		assertFalse(square.isValidThresholdHeatDamageTemperature(
				square.getThresholdColdDamageTemperature(Temperature.CELCIUS),Temperature.CELCIUS));
	}
	
	@Test
	public final void isValidIncrementSizeHeatDamage() {
		assertFalse(square.isValidIncrementSizeHeatDamage(-1));
		assertFalse(square.isValidIncrementSizeHeatDamage(0));
		assertTrue(square.isValidIncrementSizeHeatDamage(50));
	}	
	
	@Test 
	public final void setIncrementSizeHeatDamage_legalCase() {
		square.setIncrementSizeHeatDamage(32.6, Temperature.CELCIUS);
		assertEquals(0,Double.compare(32.6,square.getIncrementSizeHeatDamage(Temperature.CELCIUS)));
	}
	
	@Test (expected=IllegalArgumentException.class)
	public final void setIncrementSizeHeatDamage_illegalCase() {
		square.setIncrementSizeHeatDamage(0, Temperature.CELCIUS);
	}
		
	@Test
	public final void calculateHeatDamage(){
		square.setTemperature(30, Temperature.CELCIUS);
		assertEquals(0, square.calculateHeatDamage() );	

		square.setTemperature(35, Temperature.CELCIUS);
		assertEquals(0, square.calculateHeatDamage());
		
		square.setTemperature(Temperature.CELCIUS.convertTo(51, Temperature.FAHRENHEIT), Temperature.FAHRENHEIT);
		assertEquals(1, square.calculateHeatDamage());
		
		square.setTemperature(Temperature.CELCIUS.convertTo(66, Temperature.KELVIN),Temperature.KELVIN);
		assertEquals(2, square.calculateHeatDamage());
	
	}
	
	@Test
	public final void calculateColdDamage(){
		square.setTemperature(30, Temperature.CELCIUS);
		assertEquals(0, square.calculateColdDamage() );	

		square.setTemperature(-6, Temperature.CELCIUS);
		assertEquals(1, square.calculateColdDamage());
		
		square.setTemperature(Temperature.CELCIUS.convertTo(-6, Temperature.FAHRENHEIT), Temperature.FAHRENHEIT);
		assertEquals(1, square.calculateColdDamage());
		
		square.setTemperature(Temperature.CELCIUS.convertTo(-16, Temperature.KELVIN),Temperature.KELVIN);
		assertEquals(2, square.calculateColdDamage());
	}
	
	@Test
	public final void setMadeOfSlipperyMaterial(){
		square.setMadeOfSlipperyMaterial(true);
		assertEquals(true, square.isMadeOfSlipperyMaterial());
		
		square.setMadeOfSlipperyMaterial(false);
		assertEquals(false, square.isMadeOfSlipperyMaterial());
		
	}
	
	@Test
	public final void isSlippery(){
		square.setMadeOfSlipperyMaterial(false);
		square.setTemperature(0, Temperature.CELCIUS);
		square.setHumidity(0);
		assertFalse(square.isSlippery());
		
		square.setMadeOfSlipperyMaterial(true);
		square.setTemperature(0, Temperature.CELCIUS);
		square.setHumidity(0);
		assertTrue(square.isSlippery());
		
		square.setMadeOfSlipperyMaterial(false);
		square.setTemperature(1, Temperature.CELCIUS);
		square.setHumidity(99);
		assertFalse(square.isSlippery());
		
		square.setMadeOfSlipperyMaterial(false);
		square.setTemperature(1, Temperature.CELCIUS);
		square.setHumidity(100);
		assertTrue(square.isSlippery());
		
		square.setMadeOfSlipperyMaterial(false);
		square.setTemperature(-1, Temperature.CELCIUS);
		square.setHumidity(10);
		assertFalse(square.isSlippery());
		
		square.setMadeOfSlipperyMaterial(false);
		square.setTemperature(-1, Temperature.CELCIUS);
		square.setHumidity(11);
		assertTrue(square.isSlippery());
	}
	
	@Test
	public final void calculateInhabitability() {
		square.setTemperature(100, Temperature.CELCIUS);
		square.setHumidity(100);
		assertEquals(0,Double.compare(-8,square.calculateInhabitability()));
	}
	
	@Test
	public final void addBorders_addOne(){
//		square.addBorders(Direction.NORTH);
		assertTrue(square.hasBorder(Direction.NORTH));
		assertFalse(square.hasBorder(Direction.EAST));
		assertFalse(square.hasBorder(Direction.SOUTH));
		assertFalse(square.hasBorder(Direction.WEST));
		assertFalse(square.hasBorder(Direction.CEILING));
		assertFalse(square.hasBorder(Direction.FLOOR));
	}
	
	@Test
	public final void addBorders_sameBorders() {
		square.addBorders(new Border (Direction.NORTH, new Wall()));
		square.addBorders(new Border (Direction.NORTH, new Wall()));
		assertTrue(square.hasBorder(Direction.NORTH));
		assertFalse(square.hasBorder(Direction.EAST));
		assertFalse(square.hasBorder(Direction.SOUTH));
		assertFalse(square.hasBorder(Direction.WEST));
		assertFalse(square.hasBorder(Direction.CEILING));
		assertFalse(square.hasBorder(Direction.FLOOR));
	}
	
	@Test
	public final void removeBorders() {
		square.addBorders(new Border (Direction.NORTH, new Wall()));
		square.addBorders(new Border (Direction.SOUTH, new Wall()));
		assertTrue(square.hasBorder(Direction.NORTH));
		square.removeBorders(Direction.NORTH);
		assertFalse(square.hasBorder(Direction.NORTH));
		
		square.removeBorders(Direction.NORTH);
		assertFalse(square.hasBorder(Direction.NORTH));
	}
	

	@Test
	public final void hasBorders() {
		square.addBorders(new Border (Direction.NORTH, new Wall()));
		assertTrue(square.hasBorder(Direction.NORTH));
		assertFalse(square.hasBorder(Direction.EAST));
	}
	
	@Test
	public final void isValidConstantForWeightedAverageOfTemperature() {
		assertTrue(square.isValidConstantForWeightedAverageOfTemperature(0.1));
		assertTrue(square.isValidConstantForWeightedAverageOfTemperature(0.4));
		assertTrue(square.isValidConstantForWeightedAverageOfTemperature(0.20));
		
		assertFalse(square.isValidConstantForWeightedAverageOfTemperature(0.41));
		assertFalse(square.isValidConstantForWeightedAverageOfTemperature(0.09));
	}
	
	@Test
	public final void setConstantForWeightedAverageOfTemperature_legalCase() {
		square.setConstantForWeightedAverageOfTemperature(0.2);
		assertEquals(0,Double.compare(0.2, square.getConstantForWeightedAverageOfTemperature()));
	}

	@Test (expected=IllegalArgumentException.class)
	public final void setConstantForWeightedAverageOfTemperature_illegalCase() {
		square.setConstantForWeightedAverageOfTemperature(0.5);
	}
	
	@Test
	public final void merge() {
		Square secondSquare = new Square();
		double squareOneBeforeTemperature = square.getTemperature(Temperature.CELCIUS);
		double squareTwoBeforeTemperature = secondSquare.getTemperature(Temperature.CELCIUS);
		double squareOneBeforeHumidity = square.getHumidity();
		double squareTwoBeforeHumidity = secondSquare.getHumidity();
		
		square.mergeWith(secondSquare, Direction.NORTH);
		
		double expectedTemperatureAfterMerging = square.calculateWeightedAverage(
							squareOneBeforeTemperature, squareTwoBeforeTemperature);
		double expectedHumidityAfterMerging = square.calculateAverage(
							squareOneBeforeHumidity, squareTwoBeforeHumidity);
		
		
		assertEquals(0,Double.compare(expectedTemperatureAfterMerging,square.getTemperature(Temperature.CELCIUS)));
		assertEquals(0,Double.compare(expectedHumidityAfterMerging,square.getHumidity()));
		assertEquals(0,Double.compare(square.getTemperature(Temperature.CELCIUS), 
										secondSquare.getTemperature(Temperature.CELCIUS)));	
		assertEquals(0,Double.compare(square.getHumidity(), secondSquare.getHumidity()));
	}
	
	@Test
    public final void calculateAverage() {
            assertEquals(0,Double.compare(1.5, square.calculateAverage(1, 2)));
            assertEquals(0,Double.compare(2, square.calculateAverage(1,3)));
            assertEquals(0,Double.compare(9.25, square.calculateAverage(0,18.5)));
    }
    
    @Test
    public final void calculateWeightedAverage() {
            assertEquals(0,Double.compare(16.605,square.calculateWeightedAverage(11.25,20)));
    }
    
    @Test
    public final void calculateWeight() {
            double weightNumberOne = square.calculateWeight(11.25,15.625);
            double weightNumberTwo = square.calculateWeight(20,15.625);
            
            assertEquals(0,Double.compare(2,weightNumberOne+weightNumberTwo));
            assertEquals(0,Double.compare(0.776,weightNumberOne));
            assertEquals(0,Double.compare(1.224,weightNumberTwo));
    }	
    
    @Test 
    public final void getBorder(){
    	assertEquals(true,squareNorthBorder.getBorder(Direction.NORTH).equals( northDoorBorder));
    	assertTrue(squareNorthBorder.getBorder(Direction.SOUTH) == (null));
    }
    @Test
    public final void  termination(){
    	
    	assertFalse(squareNorthBorder.getBorder(Direction.NORTH) == null);
    	assertFalse(squareNorthBorder.isTerminated());
    	
    	squareNorthBorder.terminate();
    	
    	assertTrue(squareNorthBorder.getBorder(Direction.NORTH) == null);
    	assertTrue(squareNorthBorder.isTerminated());
    }
    
    @Test
    public final void canHaveAsBorder_Legal(){
    	assertTrue(squareNorthBorder.canHaveAsBorder(ceilingDoorBorder));
    	
    	squareNorthBorder.terminate();
    	assertTrue(squareNorthBorder.canHaveAsBorder(null));
    	
    }
    
    @Test
    public final void canHaveAsBorder_Illegal(){
    	
    	assertFalse(squareNorthBorder.canHaveAsBorder(null));
    	
    	squareNorthBorder.terminate();
    	assertFalse(squareNorthBorder.canHaveAsBorder(ceilingDoorBorder));
    	
    }
    
    @Test
    public final void hasProperBorder_Legal(){
    	assertTrue(squareNorthBorder.hasProperBorder(Direction.NORTH));
    	assertTrue(squareNorthBorder.hasProperBorder(Direction.SOUTH));
    }
    
    @Test
    public final void hasProperBorder_Illegal(){
    	assertFalse(squareNorthBorder.hasProperBorder(null));
    }
    
    @Test
    public final void canAddBorder_Legal(){
    	assertTrue(squareNorthBorder.canAddBorder(ceilingDoorBorder));
    	squareNorthBorder.addBorders(ceilingDoorBorder);
    	
    	assertFalse(squareNorthBorder.canAddBorder(floorDoorBorder));
    	squareNorthBorder.addBorders(floorDoorBorder);
    	assertFalse(squareNorthBorder.hasBorder(Direction.FLOOR));
    	
    	Border westDoorBorder = new Border(Direction.WEST, new WallWithDoor());
    	assertTrue(squareNorthBorder.canAddBorder(westDoorBorder));
    	squareNorthBorder.addBorders(westDoorBorder);
    	
    	assertFalse(squareNorthBorder.canAddBorder(southOpenDoorBorder));
    	assertTrue(squareNorthBorder.canAddBorder(new Border(Direction.SOUTH, new Wall())));
    	
    }
    
    @Test
    public final void canAddBorder_Illegal(){
    	
    	squareNorthBorder.addBorders(ceilingDoorBorder);
    	assertFalse(squareNorthBorder.canAddBorder(ceilingDoorBorder));
    	
    	squareNorthBorder.setNeighbour(Direction.SOUTH, square);
    	assertFalse(squareNorthBorder.canAddBorder(southOpenDoorBorder));
    }
    
    @Test
    public final void removeBorder_Illegal(){
    	assertFalse(squareNorthBorder.canBeRemoved(Direction.NORTH));
    }
    
    
    //*******************************************
    //        Tests on different square types   *
    //*******************************************
    
    @Test
    public final void testRock(){
    	//Test impossible removal:
    	Rock rock = new Rock();
    	rock.removeBorders(Direction.NORTH);
    		assertTrue(rock.hasBorder(Direction.NORTH));
    		
    	((Square) rock).removeBorders(Direction.NORTH);
    		assertTrue(rock.hasBorder(Direction.NORTH));
    	
    	//Test modify border:
    	Border wallborder = new Border(Direction.NORTH, new Wall());
    	
    		//test if original borderobstacle differs from the one in wallborder
    		assertFalse(rock.getBorder(Direction.NORTH).getObstacle().equals(wallborder.getObstacle()));
    	
    		rock.modifyBorder(wallborder);
    		//test if new borderobstacle is the same as the one in wallborder
    		assertTrue(rock.getBorder(Direction.NORTH).getObstacle().equals(wallborder.getObstacle()));
    	
    	//Test humidity
    	rock.setHumidity(10);
    	assertFalse(rock.getHumidity() == (10));
    }
    
    @Test
    public final void testTeleport(){
    	Square destination = new Square(10, Temperature.CELCIUS, 20);
    	Square destination2 = new Square(new Border(Direction.NORTH, new WallWithDoor(true)));
    	Teleport teleport = new Teleport();
    	
    	WallWithDoor deur = new WallWithDoor(true);
    	
    	//test if neighbours are set as possible destination
    	teleport.addBorders(new Border(Direction.SOUTH, deur));
    	teleport.setNeighbour(Direction.SOUTH, destination2);
    	assertTrue(((Square)teleport).getDirectDestinations().size() == 1);
    	
    	//test if addition destinations are also set:
    	teleport.addTeleportDestination(destination);
    	assertTrue(((Square)teleport).getDirectDestinations().size() == 2);
    	
    	//test if a random destination is picked from the 2 options:
    	int temp = (int) (teleport.teleport().getTemperature(Temperature.CELCIUS));
    	boolean test = temp == 10 || temp == 20 ;
    	assertTrue(test);
    	
    	//trying to remove Neighbour via destination (can't be done)
    	teleport.removeTeleportDestination(destination2);
    	assertTrue(teleport.getDirectDestinations().size() == 2);
    	
    	//removing the previously added destination (can be done)
    	teleport.removeTeleportDestination(destination);
    	assertTrue((teleport).getDirectDestinations().size() == 1);
    	assertTrue((teleport).getDirectDestinations().get(0).equals(destination2));
    }
    
    @Test
    public final void testTransparant(){
    	Transparant transparant = new Transparant();
    	
    	//Add border legal
    	assertTrue(transparant.canAddBorder(southOpenDoorBorder));
    	transparant.addBorders(southOpenDoorBorder);
    	assertTrue(transparant.hasBorder(Direction.SOUTH));
    	
    	//remove border legal
    	assertTrue(transparant.canBeRemoved(Direction.SOUTH));
    	assertTrue(transparant.canBeRemoved(Direction.NORTH));
    	transparant.removeBorders(Direction.NORTH);
    	assertTrue(transparant.hasBorder(Direction.SOUTH));
    	assertFalse(transparant.hasBorder(Direction.NORTH));
    	
    	//remove border illegal
    	assertFalse(transparant.canBeRemoved(Direction.SOUTH));
    	transparant.removeBorders(Direction.SOUTH);
    	assertTrue(transparant.hasBorder(Direction.SOUTH));
    	
    	//add border illegal case
    	assertFalse(transparant.canAddBorder(ceilingDoorBorder));
    	transparant.addBorders(ceilingDoorBorder);
    	assertFalse(transparant.hasBorder(Direction.CEILING));
    }
    
    @Test
    public final void testCanReach(){
    	Border eastWall = new Border(Direction.EAST, new Wall());
    	Border westWall = new Border(Direction.WEST, new Wall());
    	Border westDoor = new Border(Direction.WEST, new WallWithDoor());
    	Border eastDoor = new Border(Direction.EAST, new WallWithDoor());
    	
    	Square square1 = new Square(eastWall);
    	Square square2 = new Square(westWall);
    	Square square3 = new Square();
    	Square square4 = new Square(eastDoor);
    	Square square5 = new Square(westDoor);
    	square1.setNeighbour(Direction.NORTH, square2);
    	square2.setNeighbour(Direction.SOUTH, square1);
    		assertTrue(square1.hasNeighbour( Direction.NORTH));
    		assertTrue(square2.hasNeighbour(Direction.SOUTH));
    		assertTrue(square1.getNeighbour(Direction.NORTH).equals(square2));
    	
    	//trivial case, two neighbours, and a square that is no neighbour.
    	assertTrue(square1.canReach(square2, new ArrayList<SquareInterface>()));
    	assertTrue(square2.canReach(square1, new ArrayList<SquareInterface>()));
    	assertFalse(square1.canReach(square3, new ArrayList<SquareInterface>()));
    	assertFalse(square2.canReach(square3, new ArrayList<SquareInterface>()));
    	
    	//removing the neighbours.
    	square1.removeNeighbour(Direction.NORTH);
    	square2.removeNeighbour(Direction.SOUTH);
    		assertFalse(square1.hasNeighbour(Direction.NORTH));
    		assertFalse(square2.hasNeighbour(Direction.SOUTH));
    	
    	//testing that square1 can't reach square2 anymore, since they are no longer neighbours.
    	assertFalse(square1.canReach(square2, new ArrayList<SquareInterface>()));
    	assertFalse(square2.canReach(square1, new ArrayList<SquareInterface>()));
    	
    	//now we set a Wall between 2 squares and test that they can't be reached.
    	square1.setNeighbour(Direction.EAST, square2);
    	square2.setNeighbour(Direction.WEST, square1);
    		assertTrue(square1.hasNeighbour( Direction.EAST));
    		assertTrue(square2.hasNeighbour(Direction.WEST));
		assertFalse(square1.canReach(square2, new ArrayList<SquareInterface>()));
    	assertFalse(square2.canReach(square1, new ArrayList<SquareInterface>()));
    	
    	//removing the neighbours.
    	square1.removeNeighbour(Direction.EAST);
    	square2.removeNeighbour(Direction.WEST);
    		assertFalse(square1.hasNeighbour(Direction.EAST));
    		assertFalse(square2.hasNeighbour(Direction.WEST));
    	
    	//Testing if 3 squares are linked together, that we can reach square3 starting from square1 [1][2][3];
    	square1.setNeighbour(Direction.NORTH, square2);
    	square2.setNeighbour(Direction.SOUTH, square1);
    	square2.setNeighbour(Direction.EAST, square3);
    	square3.setNeighbour(Direction.WEST, square2);
    		assertTrue(square1.hasNeighbour(Direction.NORTH));
    		assertTrue(square2.hasNeighbour(Direction.SOUTH));
    		assertTrue(square2.hasNeighbour(Direction.EAST));
    		assertTrue(square3.hasNeighbour(Direction.WEST));
    	
    	List<SquareInterface> list = new ArrayList<SquareInterface>();
    	list.add(square2);
    		
    	assertTrue(square1.canReach(square3, list));
    	assertTrue(square3.canReach(square1, list));
    	
    	//removing the neighbours.
    	square1.removeNeighbour(Direction.NORTH);
    	square2.removeNeighbour(Direction.SOUTH);
    	square2.removeNeighbour(Direction.EAST);
    	square3.removeNeighbour(Direction.WEST);
    		assertFalse(square1.hasNeighbour(Direction.NORTH));
    		assertFalse(square2.hasNeighbour(Direction.SOUTH));
    		assertFalse(square2.hasNeighbour(Direction.EAST));
    		assertFalse(square3.hasNeighbour(Direction.WEST));
    	
    	//Same test with a wall in between the first and second square [1]|wall|[2][3];
    	square1.setNeighbour(Direction.EAST, square2);
    	square2.setNeighbour(Direction.WEST, square1);
    	square2.setNeighbour(Direction.NORTH, square3);
    	square3.setNeighbour(Direction.SOUTH, square2);
    		assertTrue(square1.hasNeighbour(Direction.EAST));
    		assertTrue(square2.hasNeighbour(Direction.WEST));
    		assertTrue(square2.hasNeighbour(Direction.NORTH));
    		assertTrue(square3.hasNeighbour(Direction.SOUTH));
    	assertFalse(square1.canReach(square3, new ArrayList<SquareInterface>()));
    	assertTrue(square2.canReach(square3, new ArrayList<SquareInterface>()));
    	
    	//Testing if a square can be reached, if there is a door between the squares [1](door)[2];
    	square1.addBorders(westDoor);
    	square2.addBorders(eastDoor);
    		assertTrue(square1.hasBorder(Direction.WEST));
    		assertTrue(square2.hasBorder(Direction.EAST));
    	square1.setNeighbour(Direction.WEST, square2);
    	square2.setNeighbour(Direction.EAST, square1);
    		assertTrue(square1.hasNeighbour(Direction.WEST));
    		assertTrue(square2.hasNeighbour(Direction.EAST));
    	assertTrue(square1.canReach(square2, new ArrayList<SquareInterface>()));
    	assertTrue(square2.canReach(square1, new ArrayList<SquareInterface>()));
    	
    	//removing the borders and neighbours
    	square2.removeNeighbour(Direction.EAST);
    	square1.removeNeighbour(Direction.WEST);
    		assertFalse(square2.hasNeighbour(Direction.EAST));
    		assertFalse(square1.hasNeighbour(Direction.WEST));
    	square1.removeBorders(Direction.WEST);
    	square2.removeBorders(Direction.EAST);
    		assertFalse(square1.hasBorder(Direction.WEST));
    		assertFalse(square2.hasBorder(Direction.EAST));
    		
    	//Testing a more complex structure, 2 squares neighbouring with a border in between, neighbouring 2 neigbouring bordes with a wall.
    	//[1]|wall|[2]
    	//[3](door)[4]
    	square1.setNeighbour(Direction.EAST, square2);
    	square2.setNeighbour(Direction.WEST, square1);
    	
    	square4.setNeighbour(Direction.EAST, square5);
    	square5.setNeighbour(Direction.WEST, square4);
    	
    	square1.setNeighbour(Direction.SOUTH, square4);
    	square4.setNeighbour(Direction.NORTH, square1);
    	
    	square2.setNeighbour(Direction.SOUTH, square5);
    	square5.setNeighbour(Direction.NORTH, square2);
    	
    	assertTrue(square1.canReach(square2, new ArrayList<SquareInterface>()));
    	assertTrue(square2.canReach(square1, new ArrayList<SquareInterface>()));
    	
    	//Testing the simpelest teleport case two non-neighbouring squares, where the first one teleports to the second (not vica versa)...
    	//[1 Teleports to 2]///[2];
    	Teleport teleport1 = new Teleport();
    	teleport1.addTeleportDestination(square3);
    	
    	assertTrue(teleport1.canReach(square3, new ArrayList<SquareInterface>()));
    	assertFalse(square3.canReach(teleport1, new ArrayList<SquareInterface>()));
    	
    	//adding a second destination to teleport. (the 'complex' structure.)
    	teleport1.addTeleportDestination(square1);
    	assertTrue(teleport1.canReach(square5, new ArrayList<SquareInterface>()));
    	assertFalse(square5.canReach(teleport1, new ArrayList<SquareInterface>()));
    	
    }
}